package com.yuanli.card.manage.service;

import com.yuanli.card.enumeration.CardPeriodEnum;
import com.yuanli.card.enumeration.CardStatusEnum;
import com.yuanli.card.pojo.CardFlow;
import com.yuanli.card.utils.CommonUtil;
import com.yuanli.card.utils.DateUtils;
import com.yuanli.card.utils.JsonMapper;
import com.yuanli.card.utils.SHA1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by layne on 2018/12/6.
 */
public abstract class AbstractAbility {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    private RestTemplate rest;

    {
        RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
        rest = restTemplateBuilder
                .interceptors(new LogHttpRequestInterceptor(logger, Charset.forName("UTF-8")))
                .build();
    }

    protected ExecutorService executorService = Executors.newCachedThreadPool();

    /**
     * @param tClass
     * @param url
     * @param mediaType
     * @param method
     * @param params
     * @param <T>
     * @return
     */
    protected <T> T invoke(Class<T> tClass, String url, String mediaType, String method, Map<String, String> params) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType(mediaType));
        ResponseEntity<T> entity = rest.exchange(url,
                HttpMethod.resolve(method.toUpperCase()),
                new HttpEntity<>(headers),
                tClass, params);
        return entity.getBody();
    }

    protected <T> T invokeWithRequestBody(Class<T> tClass, String url, String mediaType, String method, Map<String, String> params, String jsonBody) {
        HttpHeaders headers = new HttpHeaders();
        logger.info("请求地址:{},请求参数:{}", url, JsonMapper.toJsonString(params));
        headers.setContentType(MediaType.parseMediaType(mediaType));
        ResponseEntity<T> entity = rest.exchange(url,
                HttpMethod.resolve(method.toUpperCase()),
                new HttpEntity<>(jsonBody, headers),
                tClass, params);
        return entity.getBody();
    }

    /**
     * EC加密方式 token
     *
     * @param params
     * @param ability
     * @return
     */
    protected void setToken(Map<String, String> params, ChannelInterface.AbilitiesBean.AbilityBean ability) {
        //token = (appid + httpClientPwd + transid)
        String appid = (String) ability.getParams().get("appid");
        String httpClientPwd = (String) ability.getParams().get("httpClientPwd");
        //transid事务编码，由物联卡集团客户按照相应规则自主生成(不可超过48位)。
        //生成规则：APPID+YYYYMMDDHHMISS+8位数字序列（此序列由集团客户自主生成，比如从00000001开始递增等等）
        //transid样例：1000012014101615303080000001
        String transid = appid + DateUtils.simpleDateFormat(DateUtils.YYYYMMDDHHMMSS_1).format(new Date()) + CommonUtil.randomNumber(8);
        params.put("transid", transid);
        params.put("token", SHA1.getSHA1(appid, httpClientPwd, transid));
    }

    /**
     * 批量停复机
     *
     * @param ability
     */
    public abstract List<String> batchStopOpen(ChannelInterface.AbilitiesBean.AbilityBean ability, Map<String, Object> paramsIn);

    /**
     * 批量取消测试期
     *
     * @param abilityBean
     * @param paramsIn
     */
    public abstract void cancelTestPeriod(ChannelInterface.AbilitiesBean.AbilityBean abilityBean, Map<String, Object> paramsIn);


    /**
     * 查询用户信息
     *
     * @param abilityBean
     * @param paramsIn
     */
    public CardStatusEnum queryUserStatus(ChannelInterface.AbilitiesBean.AbilityBean ability, Map<String, Object> paramsIn) {
        return null;
    }

    /**
     * 省公司调用该接口可批量查询所属物联卡的在线状态信息，一次最多100个。
     *
     * @param ability
     * @param paramsIn
     */
    public Map<String, Integer> batchQueryGprsStatus(ChannelInterface.AbilitiesBean.AbilityBean ability, Map<String, Object> paramsIn) {
        return null;
    }

    /**
     * 单批次GPRS查询
     *
     * @param iccids
     * @param ability
     * @param paramsIn
     * @return
     */
    private Map<String, Integer> singleBatchQueryGprsStatus(List<String> iccids, ChannelInterface.AbilitiesBean.AbilityBean ability, Map<String, String> paramsIn) {
        return null;
    }

    /**
     * 省公司客户根据卡号（imsi、msisdn、iccid三个中任意一个），查询物联卡当前生命周
     *
     * @param ability
     * @param paramsIn
     */
    public Map<String, CardPeriodEnum> batchQueryCardLifeCycle(ChannelInterface.AbilitiesBean.AbilityBean ability, Map<String, Object> paramsIn) {
        return null;
    }

    /**
     * 省公司可以查询所属物联卡近期GPRS流量使用情况，批量查询多个用户、指定日期的GPRS使用量
     * （仅支持查询最近7天中某一天的数据，一次最多查询100张卡）。
     *
     * @param ability
     * @param paramsIn
     */
    public Map<String, CardFlow> batchGprsUsedByDate(ChannelInterface.AbilitiesBean.AbilityBean ability, Map<String, Object> paramsIn) {
        return null;
    }

    /**
     * @param iccids
     * @param ability
     * @param paramsIn
     */
    private Map<String, CardFlow> singleBatchGprsUsedByDate(List<String> iccids, ChannelInterface.AbilitiesBean.AbilityBean ability,
                                                            Map<String, String> paramsIn) {
        return null;
    }

    /**
     * 省公司可以通过卡号（msisdn\iccid\imsi，单卡）
     * 查询省属物联卡当月流量共享的实时使
     *
     * @param ability
     * @param paramsIn
     */
    public Map<String, CardFlow> queryGprsShare(ChannelInterface.AbilitiesBean.AbilityBean ability, Map<String, Object> paramsIn) {
        return null;
    }

    /**
     * 省公司可以通过卡号（msisdn\iccid\imsi，不超过20张卡）
     * 查询省属物联卡当月流量共享的实时使用情况。
     *
     * @param ability
     * @param paramsIn
     */
    public Map<String, CardFlow> batchQueryGprsShare(ChannelInterface.AbilitiesBean.AbilityBean ability, Map<String, Object> paramsIn) {
        return null;
    }

    /**
     * 集团客户可以根据ICCID、IMSI、MSISDN任意1个码号，批量按套餐查询所属物联卡当月套餐内GPRS流量实时使用情况。
     * 每次查询能力最大不超过100张卡
     *
     * @param ability
     * @param paramsIn
     */
    public Map<String, CardFlow> batchQueryRealtimeGprsInfo(ChannelInterface.AbilitiesBean.AbilityBean ability, Map<String, Object> paramsIn) {
        return null;
    }

    /**
     * @param ability
     * @param paramsIn
     * @return
     */
    public CardFlow gprsRealtimeInfo(ChannelInterface.AbilitiesBean.AbilityBean ability, Map<String, Object> paramsIn) {

        return null;
    }

    /**
     * 将传入的list字符串用下划线拼接起来xxx_xxx
     *
     * @param iccids
     * @return
     */
    private String getIccidStr(List<String> iccids) {
        StringBuilder sb = new StringBuilder();
        iccids.forEach(s -> sb.append(s + "_"));
        sb.deleteCharAt(sb.length());
        return sb.toString();
    }

    /**
     * @param cardNos
     * @param limit
     * @return
     */
    protected List<List<String>> subList(List<String> cardNos, int limit) {
        List<List<String>> integerList = new ArrayList<>();
        if (cardNos.size() > limit) {
            for (int l = 0; l < (cardNos.size() / limit) + 1; l++) {
                integerList.add(cardNos.subList(limit * l, limit * (l + 1) > cardNos.size() ? cardNos.size() : limit * (l + 1)));
            }
        }
        return integerList;
    }
}
